package org.wannatrak.android.service;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpProtocolParams;
import org.json.JSONException;
import org.json.JSONObject;
import org.wannatrak.android.enums.HttpRequestMethod;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.*;

/**
 * @Author: Maksim Tulupov maxtulupov@gmail.com
 * @Date: $Date: 2011-11-24 11:27:45 +0000 (Thu, 24 Nov 2011) $ 12:10:39 PM
 * @version: $Revision: 30 $
 * @id: $Id: HttpService.java 30 2011-11-24 11:27:45Z maxtulupov@gmail.com $
 */
public class HttpService {

    private final int OK_CODE = 200;

    public HttpResponse sendRequest(String url, Map<String, String> params, HttpRequestMethod method) throws IOException {
        return sendRequest(url, params, null, method);
    }

    public HttpResponse sendRequest(String url, Map<String, String> params, Map<String, String> headers,
                                    HttpRequestMethod method) throws IOException {
        StringBuilder sb = new StringBuilder(url);
        switch (method) {
            case POST:
                HttpPost post = new HttpPost(url);
                if (params != null) {
                    List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                    for (String key : params.keySet()) {
                        nameValuePairs.add(new BasicNameValuePair(key, params.get(key)));
                    }
                    post.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
                }
                addHeaders(post, headers);
                return createClient().execute(post);
            case DELETE:
                if (params != null) {
                    sb.append("?");
                    for (String key : params.keySet()) {
                        sb.append(key).append("=").append(params.get(key)).append("&");
                    }
                }
                HttpDelete delete = new HttpDelete(sb.toString());
                addHeaders(delete, headers);
                return createClient().execute(delete);
            default:
                if (params != null) {
                    sb.append("?");
                    for (String key : params.keySet()) {
                        sb.append(key).append("=").append(params.get(key)).append("&");
                    }
                }
                HttpGet get = new HttpGet(sb.toString());
                addHeaders(get, headers);
                return createClient().execute(get);
        }
    }

    public HttpResponse sendRequest(String url, JSONObject content) throws IOException {
        HttpPost post = new HttpPost(url);

        StringEntity stringEntity = new StringEntity(content.toString(), "UTF-8");
        stringEntity.setContentType("text/json; charset=UTF-8");
        post.setEntity(stringEntity);
        return createClient().execute(post);
    }

    public HttpResponse sendRequest(String url, byte[] data) throws IOException {
        HttpPost post = new HttpPost(url);
        ByteArrayEntity stringEntity = new ByteArrayEntity(data);
        stringEntity.setContentType("text/json; charset=UTF-8");
        post.setEntity(stringEntity);
        return createClient().execute(post);
    }

    public boolean isResponseOk(HttpResponse response) {
        return response.getStatusLine().getStatusCode() <= 300;
    }

    public JSONObject readAsJson(HttpResponse response) throws IOException, JSONException {
        String content = readAsString(response);
        JSONObject jObject = new JSONObject(content);
        return jObject;
    }

    public JSONObject readAsJson(String content) throws IOException, JSONException {
        JSONObject jObject = new JSONObject(content);
        return jObject;
    }

    public String readAsString(HttpResponse response) throws IOException {
        InputStream content = response.getEntity().getContent();
        try {
            StringBuilder sb = new StringBuilder();
            BufferedReader br = new BufferedReader(new InputStreamReader(content));
            char[] data = new char[8192];
            int i;
            while ((i = br.read(data)) > 0) {
                sb.append(data, 0, i);
            }
            return sb.toString();
        } finally {
            content.close();
        }
    }

    private HttpClient createClient() {
        HttpParams httpParameters = new BasicHttpParams();
        HttpProtocolParams.setContentCharset(httpParameters, "UTF-8");
        HttpProtocolParams.setHttpElementCharset(httpParameters, "UTF-8");
        HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
        return new DefaultHttpClient(httpParameters);
    }

    private void addHeaders(HttpRequestBase base, Map<String, String> headers) {
        if (headers == null) {
            headers = Collections.singletonMap("Content-Type", "text/json; charset=UTF-8");
        } else if (!headers.containsKey("Content-Type")) {
            Map<String, String> temp = new HashMap<String, String>();
            temp.putAll(headers);
            temp.put("Content-Type", "text/json; charset=UTF-8");
            headers = temp;
        }
        if (headers != null) {
            for (String key : headers.keySet()) {
                base.addHeader(key, headers.get(key));
            }
        }
    }

}
